package org.dding.msc.service;

import java.util.Collection;
import java.util.Set;

import org.dding.msc.value.Value;

/**
 * The target of ServiceBuilder installations.
 * ServicesBuilders to be installed on a target should be retrieved by calling one of the {@code addService} methods
 * ({@link #addService(ServiceName, Service)}, {@link #addServiceValue(ServiceName, Value)}.
 * Notice that installation will only take place after {@link ServiceBuilder#install()} is invoked. ServiceBuilders that
 * are not installed are ignored.
 * 
 */
public interface ServiceTarget {

    /**
     * Get a builder which can be used to add a service to this target.
     *
     * @param name the service name
     * @param value the service value
     * @return the builder for the service
     */
    <T> ServiceBuilder<T> addServiceValue(ServiceName name, Value<? extends Service<T>> value);

    /**
     * Get a builder which can be used to add a service to this target.
     *
     * @param name the service name
     * @param service the service
     * @return the builder for the service
     */
    <T> ServiceBuilder<T> addService(ServiceName name, Service<T> service);

    /**
     * Add a service listener that will be added to all the ServiceBuilders installed in this target.
     *
     * @param listener the listener to add to the target
     * @return this target
     */
    ServiceTarget addListener(ServiceListener<Object> listener);

    /**
     * Add a list of service listener that will be added to all ServiceBuilders installed in this target.
     *
     * @param listeners a list of listeners to add to the target
     * @return this target
     */
    ServiceTarget addListener(ServiceListener<Object>... listeners);

    /**
     * Add a collection of service listener that will be added to all ServiceBuilders installed in this target.
     *
     * @param listeners a collection of listeners to add to the target
     * @return this target
     */
    ServiceTarget addListener(Collection<ServiceListener<Object>> listeners);

    /**
     * Add a service listener that will be added to all the ServiceBuilders installed in this target.
     *
     * @param inheritance the inheritance type for this listener
     * @param listener the listener to add to the target
     * @return this target
     */
    ServiceTarget addListener(ServiceListener.Inheritance inheritance, ServiceListener<Object> listener);

    /**
     * Add a list of service listener that will be added to all ServiceBuilders installed in this target.
     *
     * @param inheritance the inheritance type for this listener
     * @param listeners a list of listeners to add to the target
     * @return this target
     */
    ServiceTarget addListener(ServiceListener.Inheritance inheritance, ServiceListener<Object>... listeners);

    /**
     * Add a collection of service listener that will be added to all ServiceBuilders installed in this target.
     *
     * @param inheritance the inheritance type for this listener
     * @param listeners a collection of listeners to add to the target
     * @return this target
     */
    ServiceTarget addListener(ServiceListener.Inheritance inheritance, Collection<ServiceListener<Object>> listeners);

    /**
     * Remove a listener from this target, if it exists.
     *
     * @param listener the listener to remove
     * @return this target
     */
    ServiceTarget removeListener(ServiceListener<Object> listener);

    /**
     * Returns a set of the listeners added to this target.
     * 
     * @return the listeners added to this target
     */
    Set<ServiceListener<Object>> getListeners();

    /**
     * Create a sub-target using this as the parent target.
     *
     * @return the new service target
     */
    ServiceTarget subTarget();

    /**
     * Create a new batch service target, which is used to install described services in this target.
     *
     * @return the new batch service target
     */
    BatchServiceTarget batchTarget();
}
